package animix.blue.server.user.service.impl;


import animix.blue.server.common.bean.pojo.Result;
import animix.blue.server.common.bean.model.RoleRight;
import animix.blue.server.common.bean.model.User;
import animix.blue.server.common.bean.model.UserRole;
import animix.blue.server.common.bean.tool.PagedList;
import animix.blue.server.common.bean.tool.Pagination;
import animix.blue.server.common.bean.tool.UserInfo;
import animix.blue.server.common.utils.CommonUtils;
import animix.blue.server.user.mapper.RoleRightMapper;
import animix.blue.server.user.mapper.UserMapper;
import animix.blue.server.user.mapper.UserRoleMapper;
import animix.blue.server.user.service.UserService;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private RoleRightMapper roleRightMapper;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 登陆用户信息在缓存中的Key
     */
    @Value("${animix.blue.server.user.login.USER_SESSION_KEY}")
    private String USER_SESSION_KEY;

    /**
     * 登陆用户信息在缓存中的过期时间（秒）
     */
    @Value("${animix.blue.server.user.login.USER_SESSION_EXPIRE}")
    private Integer USER_SESSION_EXPIRE;

    /**
     * 登陆用户信息在缓存中的过期时间（秒）（记住我时）
     */
    @Value("${animix.blue.server.user.login.USER_SESSION_EXPIRE_REMEMBER}")
    private Integer USER_SESSION_EXPIRE_REMEMBER;

    /**
     * 用户初始密码
     */
    @Value("${animix.blue.server.user.USER_INITIAL_PASSWORD}")
    private String USER_INITIAL_PASSWORD;

    @Override
    public Result login(String username, String password) {
        return login(username, password, false);
    }

    @Override
    public Result login(String username, String password, Boolean remember) {
        // 数据校验
        if (StringUtils.isBlank(username)) {
            return Result.build(400, "用户名不能为空！");
        }
        if (StringUtils.isBlank(password)) {
            return Result.build(400, "密码不能为空！");
        }
        // 查询数据库
        User user = userMapper.getByUsername(username);
        if (user == null) {
            return Result.build(400, "用户名不存在！");
        }
        if (user.getStatus() != 1) {
            return Result.build(400, "用户被禁用！");
        }
        if (!DigestUtils.md5DigestAsHex(password.getBytes()).equals(user.getPassword())) {
            return Result.build(400, "密码不正确！");
        }
        // 清空密码
        user.setPassword(null);
        // 生成token（uuid）
        String token = CommonUtils.uuid();
        UserInfo userInfo = new UserInfo(token, user, null);
        // 获取权限
        List<UserRole> listUserRole = userRoleMapper.listByUserId(user.getId());
        if (listUserRole != null && listUserRole.size() > 0) {
            Integer[] roleIds = new Integer[listUserRole.size()];
            // List转Array（JDK8）
            roleIds = listUserRole.stream().map(UserRole::getRoleId).toArray(Integer[]::new);
            List<RoleRight> listRoleRight = roleRightMapper.listByRoleIds(roleIds);
            if (listRoleRight != null && listRoleRight.size() > 0) {
                Integer[] rightIds = new Integer[listRoleRight.size()];
                rightIds = listRoleRight.stream().map(RoleRight::getRightId).toArray(Integer[]::new);
                userInfo.setRight(rightIds);
            }
        }
        // 用户信息保存至Redis
        ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();
        valueOperations.set(USER_SESSION_KEY + ":" + token, JSON.toJSONString(userInfo));
        // 设置过期时间
        if (remember != null && remember == true) {
            stringRedisTemplate.expire(USER_SESSION_KEY + ":" + token, USER_SESSION_EXPIRE_REMEMBER, TimeUnit.SECONDS);
        } else {
            stringRedisTemplate.expire(USER_SESSION_KEY + ":" + token, USER_SESSION_EXPIRE, TimeUnit.SECONDS);
        }
        // 返回token
        return Result.ok(userInfo);
    }

    @Override
    public Result getInfoByToken(String token) {
        if (StringUtils.isBlank(token)) {
            return Result.build(400, "token无效！");
        }
        // 从Redis获取用户信息
        ValueOperations<String, String> valueOperations = stringRedisTemplate.opsForValue();
        String json = valueOperations.get(USER_SESSION_KEY + ":" + token);
        if (StringUtils.isBlank(json)) {
            return Result.build(400, "用户未登陆或已过期！");
        }
        // 重置key过期时间，保持登陆状态
        stringRedisTemplate.expire(USER_SESSION_KEY + ":" + token, USER_SESSION_EXPIRE, TimeUnit.SECONDS);
        // 转回pojo再返回，直接返回json会当字符串处理，带转移符
        UserInfo userInfo = JSON.parseObject(json, UserInfo.class);
        return Result.ok(userInfo);
    }

    @Override
    public Result logout(String token) {
        if (StringUtils.isBlank(token)) {
            return Result.build(400, "token无效！");
        }
        // token置过期
        stringRedisTemplate.expire(USER_SESSION_KEY + ":" + token, 0, TimeUnit.SECONDS);
        return Result.ok();
    }

    @Override
    public Result list(Map<String, Object> para) {
        // 分页插件
        Integer currentPage = para.get("currentPage") == null ? 1 : Integer.parseInt((String) para.get("currentPage"));
        Integer pageSize = para.get("pageSize") == null ? 10 : Integer.parseInt((String) para.get("pageSize"));
        PageHelper.startPage(currentPage, pageSize);
        // 查询
        List<User> list = userMapper.list(para);
        // 分页信息
        PageInfo pageInfo = new PageInfo(list);
        Pagination pagination = new Pagination();
        pagination.setCurrent(currentPage);
        pagination.setPageSize(pageSize);
        pagination.setTotal(pageInfo.getTotal());
        // 包装
        PagedList<User> pagedList = new PagedList();
        pagedList.setList(list);
        pagedList.setPagination(pagination);
        // 返回
        return Result.ok(pagedList);
    }

    @Override
    public Result getById(Integer id) {
        if (id != null) {
            User user = userMapper.getById(id);
            if (user != null) {
                return Result.ok(user);
            } else {
                return Result.build(400, "id不存在！");
            }
        } else {
            return Result.build(400, "id无效！");
        }
    }

    @Override
    public Result add(User user) {
        if (user == null) {
            return Result.build(400, "请求参数无效！");
        }
        // 数据验证
        // 非空验证
        if (StringUtils.isBlank(user.getUsername())) {
            return Result.build(400, "用户名不能为空！");
        }
        if (StringUtils.isBlank(user.getPassword())) {
            // 设置初始密码
            user.setPassword(USER_INITIAL_PASSWORD);
        }
        // 重复验证
        User userCheck = userMapper.getByUsername(user.getUsername());
        if (userCheck != null) {
            return Result.build(400, "用户名已存在！");
        }
        if (StringUtils.isNotBlank(user.getPhone())) {
            userCheck = userMapper.getByPhone(user.getPhone());
            if (userCheck != null) {
                return Result.build(400, "手机号已存在！");
            }
        }
        if (StringUtils.isNoneBlank(user.getEmail())) {
            userCheck = userMapper.getByEmail(user.getEmail());
            if (userCheck != null) {
                return Result.build(400, "Email已存在！");
            }
        }
        // 密码加密
        user.setPassword(DigestUtils.md5DigestAsHex(user.getPassword().getBytes()));
        // 补全属性
        user.setStatus(1);
        user.setCreated(new Date());
        user.setUpdated(new Date());
        // 添加
        userMapper.insert(user);
        return Result.ok(user);
    }

    @Override
    public Result updateById(User user) {
        if (user == null) {
            return Result.build(400, "请求参数无效！");
        }
        // 数据验证
        // id验证
        Result result = getById(user.getId());
        if (result.getCode() != 200) {
            return result;
        }
        // 非空验证
        if (StringUtils.isBlank(user.getUsername())) {
            return Result.build(400, "用户名不能为空！");
        }
        // 重复验证
        User userCheck = userMapper.getByUsername(user.getUsername());
        if (userCheck != null && !userCheck.getId().equals(user.getId())) {
            return Result.build(400, "用户名已存在！");
        }
        if (StringUtils.isNotBlank(user.getPhone())) {
            userCheck = userMapper.getByPhone(user.getPhone());
            if (userCheck != null && !userCheck.getId().equals(user.getId())) {
                return Result.build(400, "手机号已存在！");
            }
        }
        if (StringUtils.isNoneBlank(user.getEmail())) {
            userCheck = userMapper.getByEmail(user.getEmail());
            if (userCheck != null && !userCheck.getId().equals(user.getId())) {
                return Result.build(400, "Email已存在！");
            }
        }
        // 更新属性
        user.setUpdated(new Date());
        // 更新
        userMapper.updateByIdSelective(user);
        return Result.ok();
    }

    @Override
    public Result deleteById(Integer id) {
        Result result = getById(id);
        if (result.getCode() != 200) {
            return result;
        }
        // 删除
        userMapper.deleteById(id);
        return Result.ok();
    }

    @Override
    public Result deleteByIds(Integer[] ids) {
        if (ids == null || ids.length <= 0) {
            return Result.build(400, "未选择要删除的用户");
        }
        userMapper.deleteByIds(ids);
        return Result.ok();
    }

    @Override
    public Result resetPwdByIds(Integer[] ids) {
        if (ids == null || ids.length <= 0) {
            return Result.build(400, "未选择要重置密码的用户");
        }
        User user = new User();
        // 设置初始密码
        user.setPassword(USER_INITIAL_PASSWORD);
        // 密码加密
        user.setPassword(DigestUtils.md5DigestAsHex(user.getPassword().getBytes()));
        // 重置
        userMapper.updateByIdsSelective(ids, user);
        return Result.ok();
    }

    @Override
    public Result disableByIds(Integer[] ids) {
        if (ids == null || ids.length <= 0) {
            return Result.build(400, "未选择要禁用的用户");
        }
        User user = new User();
        // 状态不可用
        user.setStatus(0);
        // 禁用
        userMapper.updateByIdsSelective(ids, user);
        return Result.ok();
    }
}
